/**
 * Copyright (c) 2012-2014 All Rights Reserved.
 */
package com.easy.framwork.filters;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import com.easy.framwork.utils.StringUtils;

/**
 * 编码过滤
 * 
 * @author wy
 * @version v 0.1 2014-1-3 下午10:55:05 wy Exp $
 */
public class CharacterEncodingFilter extends OncePerRequestFilter {

    /** 编码类型 */
    private String encoding = "UTF-8";

    /** 是否强制转码 */
    private boolean forceEncoding = false;

    /**
     * @see com.easy.framwork.filters.OncePerRequestFilter#otherInit()
     */
    @Override
    protected void otherInit() throws ServletException {
        String encoding = filterConfig.getInitParameter("encoding");
        if (StringUtils.isNotBlank(encoding)) {
            this.encoding = encoding;
        }
        String force = filterConfig.getInitParameter("foceEncoding");
        forceEncoding = StringUtils.isBlank(force) || "true".equals(force);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
            request.setCharacterEncoding(this.encoding);
        }
        if (this.forceEncoding) {
            response.setCharacterEncoding(this.encoding);
            filterChain.doFilter(new EncodeHttpServletRequestWrapper(request), response);
        } else {
            filterChain.doFilter(request, response);
        }
    }

    /**
     * 重新取值的相关方法
     * 
     * @author wy
     * @version v 0.1 2014-1-3 下午11:17:17 wy Exp $
     */
    public class EncodeHttpServletRequestWrapper extends HttpServletRequestWrapper {

        /**
         * @param request
         */
        public EncodeHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
        }

        /**
         * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
         */
        @Override
        public String getParameter(String name) {
            String value = super.getParameter(name);
            return decodeValue(value);
        }

        /**
         * @see javax.servlet.ServletRequestWrapper#getParameterMap()
         */
        @Override
        @SuppressWarnings("unchecked")
        public Map<String, Object> getParameterMap() {
            Map<String, Object> params = super.getParameterMap();
            Iterator<String> iter = params.keySet().iterator();
            while (iter.hasNext()) {
                String key = (String) iter.next();
                Object v = params.get(key);
                if (v == null) {
                    continue;
                } else if (v.getClass().isArray()) {
                    String[] values = (String[]) params.get(key);
                    String[] newValues = new String[values.length];
                    for (int i = 0; i < values.length; i++) {
                        newValues[i] = decodeValue(values[i]);
                    }
                    params.put(key, newValues);
                } else {
                    String value = (String) v;
                    String newValue = decodeValue(value);
                    params.put(key, newValue);
                }
            }
            return params;
        }

        /**
         * @see javax.servlet.ServletRequestWrapper#getParameterValues(java.lang.String)
         */
        @Override
        public String[] getParameterValues(String name) {
            String[] values = super.getParameterValues(name);
            for (int i = 0; values != null && i < values.length; i++) {
                values[i] = decodeValue(values[i]);
            }
            return values;
        }

        /**
         * 参数转码
         * 
         * @param value
         * @return
         */
        private String decodeValue(String value) {
            if (StringUtils.isBlank(value)) {
                return value;
            }
            try {
                return new String(value.getBytes("ISO-8859-1"), encoding);
            }
            catch (Exception e) {

            }
            return value;
        }

    }

}
